package edu.hawaii.duedates.libraries;

import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.HttpUnitOptions;
import com.meterware.httpunit.WebConversation;
import com.meterware.httpunit.WebForm;
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebResponse;
import com.meterware.httpunit.WebTable;
import edu.hawaii.duedates.datastore.ResultsList;

/**
 * A class for retrieving information from the University of Hawaii Library System website.
 * 
 * @author Arthur Shum and Erin Kim.
 */
public class UhLibrary extends Library {
  
  /** Support serialization. */
  private static final long serialVersionUID = 1L;

  /** The URL to log in to the University of Hawaii Library System. */
  private static final String URL = 
    "http://uhmanoa.lib.hawaii.edu/cgi-bin/Pwebrecon.cgi?DB=local&PAGE=pbLogon";

  /** This library's name. */
  private static final String NAME = "University of Hawaii";
  
  /**
   * Returns the library's name.
   * 
   * @return The library's name.
   */
  public String getName() {
    return NAME;
  }

  /**
   * Default constructor.
   */
  public UhLibrary() {
    super();
  }
  
  /**
   * Convenience constructor to create a UhLibrary object, given a UH ID and a last name.
   * @param uhID The patron's UH ID number.
   * @param lastName The patron's last name.
   */
  public UhLibrary(String uhID, String lastName) {
    this.username = uhID;
    this.password = lastName;
  }
    
  /**
   * Attempts to log in to the University of Hawaii Library System.
   * 
   * @return The WebConversation instance after successful login.
   * @throws Exception If an error occurs while logging in.
   */
  private WebConversation login() throws Exception {
    // UH Library website has bogus JavaScript code.
    HttpUnitOptions.setExceptionsThrownOnScriptError(false);
    // create the conversation object which will maintain state for us
    WebConversation conversation = new WebConversation();
    WebRequest request = new GetMethodWebRequest(URL);
    WebResponse response = conversation.getResponse(request);
    WebForm form = response.getFormWithName("logonpage");
    form.setParameter("BC", this.username);
    form.setParameter("LN", this.password);
    form.submit();
    response = conversation.getCurrentPage();
    if (response.getText().contains("Sorry, Login unsuccessful")) {
      throw new Exception(NAME + ": Error while logging in.");
    }
    return conversation;
  }

  /**
   * Retrieves information about items checked out from the University of Hawaii Library System by
   * the logged-in patron. The information is stored in a table that contains ": Due" in one
   * of its cells.
   * 
   * @return A ResultsList that holds information about checked-out items.
   * @throws Exception If an error occurs while retrieving info.
   */
  @Override
  public ResultsList getInfo() throws Exception {
    try {
      WebConversation conversation = this.login();
      WebResponse response = conversation.getCurrentPage();
      WebTable[] tables = response.getTables();
      for (WebTable table : tables) {
        if (table.getText().contains(": Due")) {
          return parseResults(table);
        }
      }
      return new ResultsList();
    }
    catch (Exception e) {
      // if the exception originates from this method
      if (e.getMessage() == null) {
        throw new Exception(NAME + ": Error while retrieving information.", e);
      }
      else {
        throw new Exception(e.getMessage(), e);
      }
    }
  }

  /**
   * Parses the table containing information about checked-out items, and stores the information for
   * each item in a BorrowedItem. The table has 3 columns if "patron blocks" exist, or 4 columns if
   * there are not. If the table has 3 columns, column 0 is for the item itself, column 1 is for the
   * item type, and column 3 is for the status. If the table has 4 columns, column 0 is for renewing
   * items and the other columns are shifted by one. Each row in the table is for a separate item.
   * 
   * @param table The WebTable containing checked-out item info.
   * @return A ResultsList that holds information about checked-out items.
   */
  private ResultsList parseResults(WebTable table) {
    ResultsList results = new ResultsList();

    for (int i = 1; i < table.getRowCount(); i++) {
      String item;
      String type;
      String status;     
      // 3-column table (patron blocks exist)
      if (table.getColumnCount() == 3) {
        item = table.getCellAsText(i, 0);
        type = table.getCellAsText(i, 1);
        status = table.getCellAsText(i, 2);        
      }
      // 4-column table
      else { 
        item = table.getCellAsText(i, 1);
        type = table.getCellAsText(i, 2);
        status = table.getCellAsText(i, 3);
      }
      
      // separate title and location
      int locIndex = item.indexOf("Location: ");
      String title = item.substring(0, locIndex);
      String location = item.substring(locIndex + "Location: ".length());
      
      // format due date into YYYYMMDD form
      int dueIndex = status.indexOf("Due ");
      String dueDateStr = status.substring(dueIndex + "Due ".length());
      String mm = dueDateStr.substring(0, 2);
      String dd = dueDateStr.substring(3, 5);
      String yy = dueDateStr.substring(6, 8);
      String yyyymmddDueDate = "20".concat(yy + mm + dd); 

      // format item information for printing
      String formattedResults = "";
      formattedResults = formattedResults.concat("University of Hawaii Library System\n");
      formattedResults = formattedResults.concat("Title   :  " + title + "\n");
      formattedResults = formattedResults.concat("Location:  " + location + "\n");
      formattedResults = formattedResults.concat("Type  :  " + type + "\n");
      formattedResults = formattedResults.concat("Status:  " + status + "\n\n");

      results.add(NAME, title, yyyymmddDueDate, formattedResults);
    }
    return results;    
  }

}
